// ignore_for_file: depend_on_referenced_packages

import 'package:flutter/material.dart';
import 'package:flutter_smart_heating/common/app.dart';
import 'package:flutter_smart_heating/ui/ui.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

class BrowserConfig {
  bool isFullScreen;
  bool extendBodyBehindAppBar = false;
  Color? appBarBackgroundColor;
  Color? appBarForegroundColor;
  double? appBarElevation;
  List<dynamic> rightMenu;
  BrowserConfig({
    this.isFullScreen = false,
    this.extendBodyBehindAppBar = false,
    this.appBarBackgroundColor,
    this.appBarForegroundColor,
    this.appBarElevation,
    this.rightMenu = const [],
  });
}

// #enddocregion platform_imports
class BrowserPage extends StatefulWidget {
  const BrowserPage({super.key, this.url});
  final String? url;
  @override
  State<BrowserPage> createState() => _BrowserPageState();
}

class _BrowserPageState extends State<BrowserPage> {
  late final WebViewController _controller;
  Uri? uri;
  String? pageTitle;
  bool isFullScreen = false;
  bool isFirstLoadUrl = false;
  ValueNotifier<bool> isReadyNotifier = ValueNotifier<bool>(false);
  ValueNotifier<String> titleNotifier = ValueNotifier<String>('');
  ValueNotifier<double> progressNotifier = ValueNotifier<double>(0);
  ValueNotifier<bool> canGobackNotifier = ValueNotifier<bool>(false);
  BrowserConfig config = BrowserConfig();
  @override
  void initState() {
    super.initState();
    String? url = widget.url ?? Get.parameters['url'];
    if (url != null) {
      uri = Uri.parse(url);

      titleNotifier.value = uri?.queryParameters['title'] ?? '';

      config.isFullScreen = uri?.query.contains('--fullscreen--') ?? false;
    }
  }

  initController() {
    progressNotifier.value = 0.1;
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
        WebViewController.fromPlatformCreationParams(params)
          ..setJavaScriptMode(JavaScriptMode.unrestricted)
          ..setBackgroundColor(const Color(0x00000000))
          ..setNavigationDelegate(
            NavigationDelegate(
              onPageStarted: (String url) async {
                debugPrint('Page started loading: $url');
              },
              onProgress: (int progress) async {
                progressNotifier.value = progress / 100;
                debugPrint('WebView is loading (progress : $progress%)');
              },
              onPageFinished: (String url) async {
                debugPrint('Page finished loading: $url');
                isReadyNotifier.value = true;
                updatePageTitle();
              },
              onWebResourceError: (WebResourceError error) {
                debugPrint('''
                            Page resource error:
                            code: ${error.errorCode}
                            description: ${error.description}
                            errorType: ${error.errorType}
                            isForMainFrame: ${error.isForMainFrame}
                           ''');
              },
              onNavigationRequest: (NavigationRequest request) {
                if (request.url.startsWith('native://')) {
                  App.push(Uri.decodeComponent(request.url.substring(9)));
                  return NavigationDecision.prevent;
                }
                if (!request.url.startsWith('http')) {
                  launchUrlString(request.url);
                  return NavigationDecision.prevent;
                }
                return NavigationDecision.navigate;
              },
            ),
          )
          ..addJavaScriptChannel(
            'Toaster',
            onMessageReceived: (JavaScriptMessage message) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text(message.message)),
              );
            },
          )
          ..addJavaScriptChannel(
            'Toast',
            onMessageReceived: (JavaScriptMessage message) {
              Ui.toast(message.message);
            },
          )
          ..addJavaScriptChannel(
            'Alert',
            onMessageReceived: (JavaScriptMessage message) {
              Ui.alert(message.message);
            },
          )
          ..addJavaScriptChannel(
            'Pop',
            onMessageReceived: (JavaScriptMessage message) {
              Get.back(result: message.message);
            },
          )
          ..addJavaScriptChannel(
            'Push',
            onMessageReceived: (JavaScriptMessage message) {
              App.push(message.message);
            },
          )
          ..addJavaScriptChannel(
            'ImagePreview',
            onMessageReceived: (JavaScriptMessage message) {
              ImagePreview.show(context, url: message.message);
            },
          )
          ..addJavaScriptChannel(
            'LaunchUrlString',
            onMessageReceived: (JavaScriptMessage message) async {
              if (!await launchUrlString(message.message)) {
                Ui.toast('操作失败');
              }
            },
          );

    // #docregion platform_features
    if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }

    _controller = controller;
  }

  @override
  void dispose() {
    _controller.runJavaScript('window.stop();');
    isReadyNotifier.dispose();
    titleNotifier.dispose();
    canGobackNotifier.dispose();
    super.dispose();
  }

  updatePageTitle() async {
    String title = await _controller.getTitle() ?? '';
    if (title.isNotEmpty && !title.startsWith('http')) {
      titleNotifier.value = title;
    }
    canGobackNotifier.value = await _controller.canGoBack();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: config.extendBodyBehindAppBar,
      appBar: config.isFullScreen
          ? null
          : AppBar(
              backgroundColor: config.appBarBackgroundColor,
              foregroundColor: config.appBarForegroundColor,
              elevation: config.appBarElevation,
              title: ValueListenableBuilder(
                valueListenable: titleNotifier,
                builder: (context, value, child) {
                  return Text(value);
                },
              ),
              leading: ValueListenableBuilder(
                valueListenable: canGobackNotifier,
                builder: (context, value, child) {
                  return Row(
                    children: [
                      BackButton(
                        onPressed: () async {
                          if (await _controller.canGoBack()) {
                            _controller.goBack();
                          } else {
                            Get.back();
                          }
                        },
                      ),
                      if (value)
                        const SizedOverflowBox(
                          size: Size(20, double.infinity),
                          child: CloseButton(),
                        )
                    ],
                  );
                },
              ),
              leadingWidth: 70,
              actions: [
                if (config.rightMenu.isNotEmpty)
                  buildRightMenu()
                else
                  UiRightMenuButtonGroup(
                    onTap: () {
                      _controller.runJavaScript(
                          """var inputs = document.getElementsByTagName('input');for (var i = 0; i < inputs.length; i++) {   inputs[i].blur();  }; var textarea = document.getElementsByTagName('textarea');  for (var i = 0; i < textarea.length; i++) {   textarea[i].blur();  } """);
                    },
                    onRefresh: () {
                      _controller.reload();
                    },
                    onCopyLink: () async {
                      Ui.copyText(await _controller.currentUrl());
                    },
                  )
              ],
            ),
      body: UiLifeCycle(
        /// 页面动画完成后再加载可能会没那么卡顿
        onRouteDone: () {
          if (uri != null && !isFirstLoadUrl) {
            initController();
            _controller.loadRequest(uri!);
            isFirstLoadUrl = true;
          }
        },
        child: Stack(children: [
          ValueListenableBuilder(
            valueListenable: isReadyNotifier,
            builder: (context, value, child) {
              return value
                  ? WebViewWidget(
                      controller: _controller,
                      layoutDirection: TextDirection.rtl,
                    )
                  : Container();
            },
          ),
          ValueListenableBuilder(
            valueListenable: progressNotifier,
            builder: (context, value, child) {
              return AnimatedContainer(
                  duration:
                      value == 0 ? Duration.zero : kThemeAnimationDuration,
                  width: value * MediaQuery.of(context).size.width,
                  child: Container(
                    height: 2,
                    color: Colors.blue,
                  ),
                  onEnd: () async {
                    if (progressNotifier.value == 1) {
                      await 0.1.delay();
                      progressNotifier.value = 0;
                    }
                  });
            },
          ),
        ]),
      ),
    );
  }

  Widget buildRightMenu() {
    return IconButton(
      onPressed: () {},
      icon: const Icon(Icons.more_horiz_outlined),
    );
  }
}
